Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

keys: resolve subtle non-bug by exporting RaftLogKeyFromPrefix #82479

Merged

Conversation

nvanbenschoten
Copy link
Member

This commit resolves a subtle interaction that came tantalizingly close to a bug in StateLoader.LoadLastIndex. The method uses the StateLoader's underlying keys.RangeIDPrefixBuf to generate two keys (RaftLogPrefix and RaftLogKey) that are in use as the same time.

RangeIDPrefixBuf avoids heap allocations by sharing a single byte slice across all keys that it generates. This is why the type has the comment:

The generated keys are only valid until the next call to one of the key generation methods.

As would be expected, given this comment, the second use of the RangeIDPrefixBuf overwrote the buffer and invalidated the first key. However, it happened to get lucky and generate a new key with the same prefix as the old key. As a result, the contents of the first key did not change.

To make this aliasing more explicit and avoid this becoming a real bug in the future, we introduce a new RaftLogKeyFromPrefix function that callers can use to generate raft log entry keys from a raft log prefix.

We then use this new function to avoid some redundant encoding work elsewhere due to repeated calls to RaftLogKey.

This commit resolves a subtle interaction that came tantalizingly close
to a bug in `StateLoader.LoadLastIndex`. The method uses the
`StateLoader`'s underlying `keys.RangeIDPrefixBuf` to generate two keys
(`RaftLogPrefix` and `RaftLogKey`) that are in use as the same time.

`RangeIDPrefixBuf` avoids heap allocations by sharing a single byte
slice across all keys that it generates. This is why the type has the
comment:
> The generated keys are only valid until the next call to one of the
> key generation methods.

As would be expected, given this comment, the second use of the
`RangeIDPrefixBuf` overwrote the buffer and invalidated the first key.
However, it happened to get lucky and generate a new key with the same
prefix as the old key. As a result, the contents of the first key did
not change.

To make this aliasing more explicit and avoid this becoming a real bug
in the future, we introduce a new `RaftLogKeyFromPrefix` function that
callers can use to generate raft log entry keys from a raft log prefix.
…gKey

This commit uses the new `RaftLogKeyFromPrefix` function to avoid some
redundant encoding work elsewhere due to repeat calls to `RaftLogKey`.
Instead of repeatedly encoding the Raft log prefix, we encoded it once
and repeatedly rewrite the suffix.
@nvanbenschoten nvanbenschoten marked this pull request as ready for review June 6, 2022 18:56
@nvanbenschoten nvanbenschoten requested a review from a team as a code owner June 6, 2022 18:56
@cockroach-teamcity
Copy link
Member

This change is Reviewable

This did not belong in stateloader.go.
@nvanbenschoten nvanbenschoten force-pushed the nvanbenschoten/commentSubtle branch from 369e95d to c5497ba Compare June 6, 2022 19:17
Copy link
Contributor

@erikgrinaker erikgrinaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, thanks!

@nvanbenschoten
Copy link
Member Author

TFTRs!

bors r=tbg,erikgrinaker

@craig
Copy link
Contributor

craig bot commented Jun 7, 2022

Build succeeded:

@craig craig bot merged commit d9fd5bf into cockroachdb:master Jun 7, 2022
@nvanbenschoten nvanbenschoten deleted the nvanbenschoten/commentSubtle branch June 9, 2022 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants